package com.thoughtworks;

import com.thoughtworks.options.Library;
import com.thoughtworks.options.Option;
import com.thoughtworks.reader.InputReader;

import java.io.IOException;
import java.util.Map;

import static com.google.common.collect.Maps.newHashMap;

public class Menu {

    private final Library library;
    private Printer printer;
    private Map<Integer,Option> options = menuOptions();
    private InputReader inputReader;

    public Menu(Printer printer, Library library, InputReader inputReader) {
        this.printer = printer;
        this.library = library;
        this.inputReader = inputReader;
    }

    public void display() throws IOException {
        printInitialMenu();
        int input = validateInput();
        while(isUserChoiceAnExit(input)) {
            options.get(input).execute();
            printInitialMenu();
            input = validateInput();
        }
        options.get(0).execute();
    }

    private void printInitialMenu() {
        printer.print("Welcome to the Bangalore library!");
        for(Option option : options.values()) {
            printer.print(option.message());
        }
    }

    private int validateInput() throws IOException {
        int input = inputReader.read();

        while(!isUsersChoiceAValidOption(input)) {
            printer.print("Select a valid option!");
            input = inputReader.read();
        }

        return input;
    }

    private boolean isUsersChoiceAValidOption(int input) {
        return options.keySet().contains(input);
    }

    private boolean isUserChoiceAnExit(int input) {
        return input != 0;
    }

    private Map<Integer, Option> menuOptions() {
        Map<Integer, Option> options = newHashMap();

        options.put(0, new Option() {
            @Override
            public String message() {
                return "0) Quit";
            }

            @Override
            public void execute() {
                printer.print("Goodbye!");
                return;
            }
        });

        options.put(1, new Option() {
            @Override
            public String message() {
               return "1) List books";
            }
            @Override
            public void execute() {
                printer.print(library.listAvailableBooks());
            }
        });

        options.put(2, new Option() {
            @Override
            public void execute() throws IOException {
                printer.print("Please choose a book to checkout:");
                printer.print(library.checkoutABook(inputReader.read()));
            }

            @Override
            public String message() {
                return "2) Checkout a book";
            }
        });

        options.put(3, new Option() {
            @Override
            public void execute() throws IOException {
                printer.print("Please choose a book to return:");
                printer.print(library.returnABook(inputReader.read()));
            }

            @Override
            public String message() {
                return "3) Return a book";
            }
        });

        return options;
    }
}